package com.gemserk.infraestructure.lwjglmavenizer;
import org.apache.commons.io.output.ByteArrayOutputStream;

import java.util.jar.Attributes;


import groovy.util.CliBuilder;

import java.io.File;
import java.util.jar.Manifest;

import org.apache.commons.io.FileUtils;

public class Mavenizer {
	
	public static File createTempDirectory(String prefix){
		final File temp;
		
		temp = File.createTempFile(prefix, Long.toString(System.nanoTime()));
		
		if(!(temp.delete())) {
			throw new IOException("Could not delete temp file: " + temp.getAbsolutePath());
		}
		
		if(!(temp.mkdir())) {
			throw new IOException("Could not create temp directory: " + temp.getAbsolutePath());
		}
		
		return (temp);
	}
	
	public static File makeRelativeTo(File file, File relativeTo){
		return new File(file.getAbsolutePath().substring(relativeTo.getAbsolutePath().length()))
	}
	
	
	
	public static void main(String[] args) {
		
		CliBuilder cli = new CliBuilder(usage:"LWJGLMavenizer, use -h for more options")
		
		
		cli.with {
			b(longOpt:'binaries', args:1, argName:'binaries', 'LWJGL Binary distribution, zip file or uncompressed dir', required:true)
			s(longOpt:'sources', args:1, argName:'sources', 'LWJGL Sources distribution, zip file or uncompressed dir', required:true)
			t(longOpt:'targetDir', args:1, argName:'targetDir', 'Target dir, the artifacts will be generated here', required:true)
			v(longOpt:'version', args:1, argName:'version','Maven version of generated artifacts',required:true)
			r(longOpt:'repoUrl', args:1, argName:'repoUrl','URL of maven repository',required:false)
			i(longOpt:'repoId', args:1, argName:'repoId','ID of maven repository',required:false)
		}
		
		
		
		def options = cli.parse(args)
		
		if(!options){
			System.exit(0)
		}
		
		
		
		File targetBaseFile = new File(options.t)
		File lwjglBinaryBaseFile = new File(options.b)
		File lwjglSourceBaseFile = new File(options.s)
		def version = options.v
		def repoUrl = options.r ?: "REPOURL"
		def repoId = options.i ?: "REPOID"
		
		if(targetBaseFile.exists()){
			if(!targetBaseFile.isDirectory()){
				System.out.println("TargetDir is not a directory");
				System.exit(1)
			}
		} else {
			targetBaseFile.mkdirs()
		}
		
		if(!lwjglBinaryBaseFile.exists() || (!lwjglBinaryBaseFile.isDirectory() && !lwjglBinaryBaseFile.getAbsolutePath().endsWith(".zip"))){
			System.out.println("binaries parameter is not a zip file or directory");
			System.exit(1)
		}
		
		if(!lwjglSourceBaseFile.exists() || (!lwjglSourceBaseFile.isDirectory() && !lwjglSourceBaseFile.getAbsolutePath().endsWith(".zip"))){
			System.out.println("sources parameter is not a zip file or directory");
			System.exit(1)
		}
		
		
		
		
		
		new Mavenizer().mavenizeParseCommands(targetBaseFile.getAbsolutePath() , lwjglBinaryBaseFile.getAbsolutePath() , lwjglSourceBaseFile.getAbsolutePath() , version, repoUrl, repoId)
	}
	
	public void mavenizeParseCommands(String targetBase, String lwjglBinaryBase, String lwjglSourceBase, version, repoUrl, repoId){
		def mustDeleteDirs = []
		try{
			if(lwjglBinaryBase.endsWith(".zip")){
				System.out.println("LWJGL Binary Distribution is in Zip");
				File lwjglBinaryBaseFile = Mavenizer.createTempDirectory("lwjglExtractedBynary")
				mustDeleteDirs << lwjglBinaryBaseFile
				new ZipUtils().unzip(new File(lwjglBinaryBase), lwjglBinaryBaseFile) 
				def childrenDirs = lwjglBinaryBaseFile.list()
				if(childrenDirs.size() == 0)
					throw new Exception("Empty zip $lwjglBinaryBase")
				
				if(childrenDirs.size() == 1){
					
					def childrenDir = new File(lwjglBinaryBaseFile,childrenDirs[0])
					lwjglBinaryBase = childrenDir.getAbsolutePath()
				} else {
					lwjglBinaryBase = lwjglBinaryBaseFile.getAbsolutePath()
				}
			}
			
			if(lwjglSourceBase.endsWith(".zip")){
				System.out.println("LWJGL Source Distribution is in Zip");
				File lwjglSourceBaseFile = Mavenizer.createTempDirectory("lwjglExtractedSource")
				mustDeleteDirs << lwjglSourceBaseFile
				new ZipUtils().unzip(new File(lwjglSourceBase), lwjglSourceBaseFile)
				def childrenDirs = lwjglSourceBaseFile.list()
				if(childrenDirs.size() == 0)
					throw new Exception("Empty zip $lwjglSourceBase")
				lwjglSourceBase = lwjglSourceBaseFile.getAbsolutePath()
			}
			
			mavenize(targetBase, lwjglBinaryBase, lwjglSourceBase, version, repoUrl, repoId)
		} catch(Exception e){
			e.printStackTrace()
		} finally {
			mustDeleteDirs.each {File dir ->
				dir.deleteDir()
			}
		}
	}
	
	public void mavenize(String targetBase, String lwjglBinaryBase, String lwjglSourceBase, lwjglVersion, repoUrl, repoId){
		println BasicConstants.SOS;
		println BasicConstants.basePath;
		
		
		def targetBaseFile = new File(targetBase)
		targetBaseFile.mkdirs()
		
		
		POMBuilder pomBuilder = new POMBuilder();
		
		
		def sourceBase= lwjglSourceBase
		def jarsBase = "$lwjglBinaryBase/jar"
		def nativesBase = "$lwjglBinaryBase/native"
		
		def logs = []
		def deployCommands = []
		def installCommands = []
		
		BasicConstants.libs.each{ library ->
			
			def attached = []
			
			def natives = BasicConstants.natives[(library)];
			if(natives!=null){
				BasicConstants.SOS.each{ SO ->
					
					
					
					
					//println "$library - $SO - $ARCH - ${natives[(SO)][(ARCH)]}";
					
					def classifier = "natives-$SO";
					
					ZipUtils zutils = new ZipUtils()
					
					def zos = zutils.createZipFile(new File("$targetBase/$library-${lwjglVersion}-${classifier}.jar").getAbsolutePath())
					zutils.addManifest(zos)
					natives[(SO)].each { file -> 
						def dir = new File("$nativesBase/${BasicConstants.basePath[(SO)]}")
						zutils.zipFile(new File(dir,file).getAbsoluteFile(),dir.getAbsolutePath(),zos)
					}
					zos.close()
					
					attached << classifier
				}
			}
			
			
			
			
			
			def mavenArtifactCoords = BasicConstants.mavenId[(library)]
			mavenArtifactCoords.version = lwjglVersion
			
			String pom = pomBuilder.buildPom(mavenArtifactCoords, attached, BasicConstants.mavenDependencies[(library)])
			
			
			def sources = BasicConstants.sources[(library)]
			if(sources!=null){
				def classifier = "sources"
				def sourceFile = sources.generateSources(new File(sourceBase))
				FileUtils.copyFile(sourceFile,new File("$targetBase/$library-${lwjglVersion}-${classifier}.jar"))
				attached << classifier
			}
			
			//println pom;
			
			String pomPath = "$targetBase/${library}-pom.xml"
			File pomFile = new File(pomPath)
			pomFile.write(pom);
			
			def libraryJar = new File("$targetBase/$library-${lwjglVersion}.jar")
			FileUtils.copyFile(new File("$jarsBase/${library}.jar"),libraryJar)
			
			
			
			deployCommands << MavenDeployer.deploy(repoUrl, repoId, pomFile,libraryJar, null, targetBaseFile)
			attached.each{ classifier ->
				File artifactFile = new File(targetBaseFile,"$library-$mavenArtifactCoords.version-${classifier}.jar")
				
				deployCommands << MavenDeployer.deploy(repoUrl, repoId, pomFile, artifactFile, classifier, targetBaseFile)
			}
			
			installCommands << MavenDeployer.install(pomFile,libraryJar, null, targetBaseFile)
			attached.each{ classifier ->
				File artifactFile = new File(targetBaseFile,"$library-$mavenArtifactCoords.version-${classifier}.jar")
				
				installCommands << MavenDeployer.install(pomFile, artifactFile, classifier, targetBaseFile)
			}
		}
		
		File deployScriptLinux = new File(targetBaseFile,"deploy.sh")
		deployScriptLinux.text = deployCommands.join("\n")
		deployScriptLinux.setExecutable true
		
		File installScriptLinux = new File(targetBaseFile,"install.sh")
		installScriptLinux.text = installCommands.join("\n")
		installScriptLinux.setExecutable true
		logs.each { println it }
	}
}